// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: Apache-2.0

package user_api_serv

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"

	"gitcode.com/lvupclub/lvup-api/dao"
	"gitcode.com/lvupclub/lvup-api/dao/user_dao"
	"gitcode.com/lvupclub/proto-gen-go.git/src/user_api"
	"github.com/dchest/uniuri"
	"github.com/google/uuid"
)

type WxLoginResult struct {
	AccessToken string `json:"access_token"`
	OpenID      string `json:"openid"`
	ErrCode     int    `json:"errcode"`
	ErrMsg      string `json:"errmsg"`
}

type WxUserInfo struct {
	NickName   string `json:"nickname"`
	HeadImgUrl string `json:"headimgurl"`

	ErrCode int    `json:"errcode"`
	ErrMsg  string `json:"errmsg"`
}

func (apiImpl *UserApiImpl) loginByWechat(ctx context.Context, oauthCode string) (*user_api.LoginResponse, error) {
	//获取access token
	reqUrl := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", apiImpl.loginCfg.Wx.AppId, apiImpl.loginCfg.Wx.AppSecret, oauthCode)
	resp, err := http.Get(reqUrl)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	bodyData, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	loginResult := &WxLoginResult{}
	err = json.Unmarshal(bodyData, loginResult)
	if err != nil {
		return nil, err
	}

	if loginResult.ErrMsg != "" {
		return nil, fmt.Errorf("%s", loginResult.ErrMsg)
	}

	//获取用户信息
	reqUrl = fmt.Sprintf("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", url.QueryEscape(loginResult.AccessToken), url.QueryEscape(loginResult.OpenID))
	resp, err = http.Get(reqUrl)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	bodyData, err = io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	wxUser := &WxUserInfo{}
	err = json.Unmarshal(bodyData, wxUser)
	if err != nil {
		return nil, err
	}
	if wxUser.ErrMsg != "" {
		return nil, fmt.Errorf("%s", wxUser.ErrMsg)
	}

	//同步用户信息
	exist, err := user_dao.UserInfoDao.ExistByName(ctx, user_api.USER_TYPE_USER_TYPE_WECHAT, loginResult.OpenID)
	if err != nil {
		return nil, err
	}
	var userItem *user_dao.UserInfoDbItem
	nowTime := time.Now().UnixMilli()
	if !exist {
		userId := uuid.NewString()
		err = user_dao.UserInfoDao.Insert(ctx, &user_dao.UserInfoDbItem{
			UserId:   userId,
			UserType: user_api.USER_TYPE_USER_TYPE_WECHAT,
			UserName: loginResult.OpenID,
			BasicInfo: user_dao.BasicUserInfoDbItem{
				DisplayName:  wxUser.NickName,
				LogoUri:      wxUser.HeadImgUrl,
				UserRole:     user_api.USER_ROLE_USER_ROLE_COACH,
				PublicAccess: false,
				UserIntro:    "",
			},
			CreateTime: nowTime,
			UpdateTime: nowTime,
		})
		if err != nil {
			return nil, err
		}
		userItem, err = user_dao.UserInfoDao.GetById(ctx, userId)
		if err != nil {
			return nil, err
		}
	} else {
		userItem, err = user_dao.UserInfoDao.GetByName(ctx, user_api.USER_TYPE_USER_TYPE_WECHAT, loginResult.OpenID)
		if err != nil {
			return nil, err
		}
		if userItem.BasicInfo.DisplayName != wxUser.NickName || userItem.BasicInfo.LogoUri != wxUser.HeadImgUrl {
			userItem.BasicInfo.DisplayName = wxUser.NickName
			userItem.BasicInfo.LogoUri = wxUser.HeadImgUrl
		}
		err = user_dao.UserInfoDao.UpdateBasic(ctx, userItem.UserId, &userItem.BasicInfo, nowTime)
		if err != nil {
			return nil, err
		}
	}
	//生成session
	sessionId := uniuri.NewLen(32) + strings.ReplaceAll(uuid.NewString(), "-", "")
	dao.CacheDao.SetSession(ctx, &dao.SessionDbItem{
		SessionId: sessionId,
		UserId:    userItem.UserId,
		UserType:  user_api.USER_TYPE_USER_TYPE_WECHAT,
	})

	return &user_api.LoginResponse{
		Code:      user_api.LoginResponse_CODE_OK,
		SessionId: sessionId,
		UserInfo:  userItem.ToUserInfo(),
	}, nil
}
